#include <iostream>

using namespace std;

typedef long long ll;
const int N = 1e7 - 520;
int n, m;
// 记录节点数量
int top;
// root数组保存版本根节点编号
int root[N], a[N];

struct node {
  int l, r, val;
} tree[N * 4];

// 复制当前节点到新链路
int add(int u) {
  top++;
  tree[top] = tree[u];
  return top;
}

void build(int &u, int l, int r) {
  u = ++top;
  if (l == r) {
    tree[u].val = a[l];
    return;
  }
  int mid = (l + r) >> 1;
  build(tree[u].l, l, mid);
  build(tree[u].r, mid + 1, r);
}

void update(int &u, int l, int r, int x, int v) {
  u = add(u);
  if (l == r) {
    tree[u].val = v;
    return;
  }
  int mid = (l + r) >> 1;
  if (x <= mid) {
    update(tree[u].l, l, mid, x, v);
  } else {
    update(tree[u].r, mid + 1, r, x, v);
  }
}

int query(int u, int l, int r, int x) {
  if (l == r)
    return tree[u].val;
  int mid = (l + r) >> 1;
  if (x <= mid)
    return query(tree[u].l, l, mid, x);
  else
    return query(tree[u].r, mid + 1, r, x);
}

int main() {
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= n; i++)
    scanf("%d", &a[i]);
  build(root[0], 1, n); 
  for (int i = 1; i <= m; i++) {
    int rt, op, x, y;
    scanf("%d%d%d", &rt, &op, &x);
    if (op == 1) {
      scanf("%d", &y);
      root[i] = root[rt];
      update(root[i], 1, n, x, y);
    } else {
      printf("%d\n", query(root[rt], 1, n, x));
      root[i] = root[rt];
    }
  }
  return 0;
}
